package com.maxvision.mybatis.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import com.maxvision.mybatis.service.ImageService;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.security.RunAs;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author HuangRongFu
 * 2022/12/9 星期五21:54
 */

@Service
@Log4j2
public class ImageServiceImpl implements ImageService {

    @Override
    public ResponseEntity importImagesByCallableSubmit(MultipartFile[] multipartFiles) {

        try {
            List<MultipartFile> imageList = Arrays.asList(multipartFiles);
            int size = Runtime.getRuntime().availableProcessors() * 2;

            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(size, size, 1, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<Runnable>(size));
            List<List<MultipartFile>> imageAvg = ListUtil.splitAvg(imageList, size);
            List<Future<String>> result = new ArrayList<>();
            for (List<MultipartFile> images : imageAvg) {

                Callable<String> callable = new Callable<>() {

                    @Override
                    public String call() throws Exception {

                        log.info("线程名:" + Thread.currentThread().getName());
                        long start = System.currentTimeMillis();

                        for (MultipartFile image : images) {

                            File file = new File("src/main/resources/image/" + image.getOriginalFilename());
                            FileUtil.writeBytes(image.getBytes(), file);
                        }
                        long end = System.currentTimeMillis();
                        log.info(Thread.currentThread().getName() + "处理图像耗时: " + (end - start) + "ms");
                        return Thread.currentThread().getName() + "处理完成";
                    }
                };
                Future<String> submit = threadPoolExecutor.submit(callable);
                result.add(submit);
            }

            for (Future<String> stringFuture : result) {

                log.info("结果:" + stringFuture.get());
            }
        } catch (Exception e) {

            log.error(e.getMessage(), e);
        }

        return ResponseEntity.ok("图片处理完成");
    }

    /**
     * 等待线程结束方式一 CountDownLatch
     *
     * @param multipartFiles
     * @return
     */
    @Override
    public ResponseEntity importImagesByRunnableSubmitCountDownLatch(MultipartFile[] multipartFiles) {

        int size = Runtime.getRuntime().availableProcessors() * 2;
        CountDownLatch countDownLatch = new CountDownLatch(size);
        try {
            List<MultipartFile> imageList = Arrays.asList(multipartFiles);
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(size, size, 1, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<Runnable>(size));
            List<List<MultipartFile>> imageAvg = ListUtil.splitAvg(imageList, size);
            for (List<MultipartFile> images : imageAvg) {

                threadPoolExecutor.submit(new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {

                        log.info("线程名:" + Thread.currentThread().getName());
                        long start = System.currentTimeMillis();

                        for (MultipartFile image : images) {

                            File file = new File("src/main/resources/image/" + image.getOriginalFilename());
                            FileUtil.writeBytes(image.getBytes(), file);
                        }
                        countDownLatch.countDown();
                        long end = System.currentTimeMillis();
                        log.info(Thread.currentThread().getName() + "处理图像耗时: " + (end - start) + "ms");
                    }
                });
            }
            countDownLatch.await();
        } catch (Exception e) {

            log.error(e.getMessage(), e);
        }
        return ResponseEntity.ok("图片处理完成");
    }

    @Override
    public ResponseEntity importImagesByRunnableSubmit(MultipartFile[] multipartFiles) {

        int size = Runtime.getRuntime().availableProcessors() * 2;
        try {
            List<MultipartFile> imageList = Arrays.asList(multipartFiles);
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(size, size, 1, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<Runnable>(size));
            List<List<MultipartFile>> imageAvg = ListUtil.splitAvg(imageList, size);
            for (List<MultipartFile> images : imageAvg) {

                threadPoolExecutor.submit(new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {

                        log.info("线程名:" + Thread.currentThread().getName());
                        long start = System.currentTimeMillis();

                        for (MultipartFile image : images) {

                            File file = new File("src/main/resources/image/" + image.getOriginalFilename());
                            FileUtil.writeBytes(image.getBytes(), file);
                        }
                        long end = System.currentTimeMillis();
                        log.info(Thread.currentThread().getName() + "处理图像耗时: " + (end - start) + "ms");
                    }
                });
            }

            threadPoolExecutor.shutdown();
            while (true) {
                log.info("未完成");
                Thread.sleep(100);
                if (threadPoolExecutor.isTerminated()) {
                    log.info("执行完成");
                    break;
                }
            }

        } catch (Exception e) {

            log.error(e.getMessage(), e);
        }
        return ResponseEntity.ok("图片处理完成");
    }

    @Override
    public ResponseEntity importImagesForList(MultipartFile[] multipartFiles) {

        try {
            List<MultipartFile> imageList = Arrays.asList(multipartFiles);
            for (MultipartFile multipartFile : imageList) {
                File file = new File("src/main/resources/image/" + multipartFile.getOriginalFilename());
                FileUtil.writeBytes(multipartFile.getBytes(), file);
            }
        } catch (Exception e) {

            log.error(e.getMessage(), e);
        }
        return ResponseEntity.ok("处理完成");
    }

    @Async
    @Override
    public Future<String> async() {
        
        try {
            System.out.println("线程休眠开始");
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程休眠结束");

        return new AsyncResult<>("异步执行任务完成");
    }
    

}
